#ifndef _PACKET_H_
#define _PACKET_H_

#include "Include.h"
#include "Data.h"


#define _KEY_NONE				"0000"
#define _KEY_TICK				"1200"
#define _KEY_AGENT				"1300"
#define _KEY_WORK				"1400"
#define _KEY_WORK_END			"1500" 
#define _KEY_END_LIST			"1600" 
#define _KEY_EFFECT				"1600"
#define _KEY_FILTER				"1700"



#define _KEY_JOB_LIST			"2000"

#define _KEY_READ_SETTINGS		"3000"


class PACKET_BASE
{
protected:
	Json::Value root;

public:

	PACKET_BASE(){};

	PACKET_BASE(const std::string& cmd)
	{
		SetCMD(cmd);
		SetRendererId();
	}

	PACKET_BASE(const std::string& cmd , const Json::Value& root)
	{
		SetRoot(root); 
		SetCMD(cmd);   
		SetRendererId();
	}


	static bool GetRoot(const std::string &buf , Json::Value& root);


	static std::string GetStringS(const Json::Value&  root,const std::string& name);
	static std::string GetStringS(const Json::Value& root , const std::string& name1 ,const std::string& name2);
	std::string GetString(const std::string& name);
	std::string GetString(const std::string& name1 ,const std::string& name2 );

	static int GetIntS(const Json::Value& root , const std::string& name);
	static int	GetIntS(const Json::Value& root ,const std::string& name1 , const std::string& name2);
	int	GetInt(const std::string& name);
	int	GetInt(const std::string& name1 , const std::string& name2);

	static double	GetDoubleS(const Json::Value& root ,const std::string& name);
	static double	GetDoubleS(const Json::Value& root , const std::string& name1 , const std::string& name2);
	double	GetDouble(const std::string& name);
	double	GetDouble(const std::string& name1 , const std::string& name2);


	void SetRoot(const Json::Value& root)
	{
		this->root = root;
	}

	void SetParam(const std::string& name , const std::string& value)
	{
		root[name] = value;
	}

	void SetParam(const std::string& name , const int value)
	{
		root[name] = value;
	}

	void SetCMD(const std::string& cmd)
	{
		root["CMD"]	= cmd;
	}

	void SetRendererId()
	{
		root["RENDERER_ID"]	= Settings::GetSettings()->RENDERER_ID;
	}

	std::string GetCMD()
	{
		return GetString("CMD");
	}

	std::string GetRendererId()
	{
		return GetString("RENDERER_ID");
	}

	void SetMSG(std::string msg)
	{
		root["MSG"]	= msg;
	}

	std::string GetMSG()
	{
		return GetString("MSG");
	}

	virtual std::string Dump() = 0;

		
	std::string ToString()
	{
		Json::StyledWriter writer;  
		return writer.write( root );  
	}


};

class PACKET_TMP : public PACKET_BASE
{
public:

	PACKET_TMP(){}

	std::string Dump()
	{
		return "";
	}

};



class PACKET_TICK : public PACKET_BASE
{
public:

	PACKET_TICK() : PACKET_BASE(_KEY_TICK)
	{
	}

	PACKET_TICK(const Json::Value& root) : PACKET_BASE(_KEY_TICK , root)
	{
	}

	std::string Dump()
	{
		return "tick";
	}

};

class PACKET_READ_SETTINGS : public PACKET_BASE
{
public:

	PACKET_READ_SETTINGS() : PACKET_BASE(_KEY_READ_SETTINGS)
	{
	}

	PACKET_READ_SETTINGS(const Json::Value& root) : PACKET_BASE(_KEY_READ_SETTINGS , root)
	{
	}

	std::string Dump()
	{
		return "read settings";
	}

};


class PACKET_AGENT : public PACKET_BASE
{
public:

	PACKET_AGENT() : PACKET_BASE(_KEY_AGENT)
	{
		root["CPU"] = (int)ACE_OS::num_processors();
	}

	PACKET_AGENT(const Json::Value& root) : PACKET_BASE(_KEY_AGENT , root)
	{
	}

	int GetCPU()
	{
		return GetInt("CPU");
	}

	std::string Dump()
	{
		char buf[100];
		sprintf(buf , "CPU : %d " , GetCPU() );
		return buf;
	}


};




class PACKET_WORK : public PACKET_BASE
{
public:

	PACKET_WORK(const Json::Value& root)  : PACKET_BASE(_KEY_WORK , root)
	{
	}

	PACKET_WORK(_JOB_INFO& ji) : PACKET_BASE(_KEY_WORK)
	{
		root["jobId"] = ji.GetJobId();
		root["s3Url"] = ji.GetS3Url();
		root["resultPath"] = ji.GetResultPath();
		root["srcVideoPath"] = ji.GetSrcVideoFilePath(false);
		root["srcScriptPath"] = ji.GetSrcScriptFilePath(false);

	}
	
	_JOB_INFO GetJobInfo()
	{
		return _JOB_INFO(GetString("jobId")
			, GetString("s3Url")
			, GetString("resultPath")
			, GetString("srcVideoPath")
			, GetString("srcScriptPath")
			);
	}

	std::string Dump()
	{
		return "";
	}
	
};

class PACKET_WORK_END : public PACKET_BASE
{
public:

	PACKET_WORK_END(const Json::Value& root)  : PACKET_BASE(_KEY_WORK_END , root)
	{
	}

	PACKET_WORK_END(const std::string& job_id) : PACKET_BASE(_KEY_WORK_END)
	{
		root["jobId"] = job_id;
	};

	
	std::string GetJobId()
	{
		return GetString("jobId");
	}

	std::string Dump()
	{
		return  "JOB END : " + GetJobId();
	}
	
};

class PACKET_END_LIST : public PACKET_BASE
{
public:

	PACKET_END_LIST(const Json::Value& root)  : PACKET_BASE(_KEY_END_LIST , root)
	{
	}

	std::string Dump()
	{
		std::string content = "END LIST: ";
		for(int i = 0 ; i < root["jobIdList"].size() ; i ++)
		{
			if(i > 0)
				content += ",";
			content += root["jobIdList"][i].asCString();
		}
		
		return content;
	}

	
};

class PACKET_EFFECT : public PACKET_BASE
{
public:
	std::string GetEffectID()
	{
		return GetString("effectId");
	}

	std::string GetTempFile()
	{
		return GetString("tempFile");
	}

public:

	PACKET_EFFECT() : PACKET_BASE(_KEY_EFFECT)
	{
	};

	PACKET_EFFECT(const Json::Value& root)  : PACKET_BASE(_KEY_EFFECT , root)
	{
	}


	Json::Value& GetAnimationInfo(int index)
	{
		return root["animations"][index];
	}


	int GetAnimationSize()
	{
		return root["animations"].size();
	}

	double GetStartTime()
	{
		return GetDouble("startTime");
	}

	double GetDuration()
	{
		return GetDouble("duration");
	}

	double GetPosX()
	{
		return GetDouble("position","x");
	}

	double GetPosY()
	{
		return GetDouble("position","y");
	}

	std::string GetColorMixBlend()
	{
		Json::Value &v = root["colorMix"];
		if(!v.isNull())
			return GetStringS(v , "blend");
		return "";
	}

	_COLOR GetColorMixColor()
	{
		Json::Value &v = root["colorMix"]["color"];
		if(!v.isNull())
			return _COLOR(GetIntS(v , "red")
						, GetIntS(v , "green")
						, GetIntS(v , "blue"));
		return _COLOR();
		
	}

	double GetRotation()
	{
		return GetDouble("rotation");
	}

	double GetAlpha()
	{
		return GetDouble("alpha");
	}

private:
	double GetSizeW()
	{
		return GetDouble("size","width");
	}

	double GetSizeH()
	{
		return GetDouble("size","height");
	}

	_SIZE AdjustSize();
public:


	_OBJ_INFO GetObjectInfo(const std::string& job_id);

	std::string Dump()
	{
		char buf[1024 * 2];
		memset(buf , 0x00 , 1024 * 2);
 
		sprintf(buf , "EFFECT : ID[%s] StartTime[%.0f] Duration[%.0f] POS[%.0f,%.0f] Rotation[%.0f] Size[%.0f,%.0f] " 
			, GetEffectID().c_str() , GetStartTime() , GetDuration() , GetPosX() , GetPosY() 
			, GetRotation() , GetSizeW() , GetSizeH() );

		return buf;
	}
	
};


class PACKET_JOBLIST : public PACKET_BASE
{
public:

	std::string GetJobId(int index)
	{
		return GetStringS(root["body"][index] , "jobId");
	}

	std::string GetS3Url(int index)
	{
		return GetStringS(root["body"][index],"s3Url");
	}

	std::string GetResultPath(int index)
	{
		return GetStringS(root["body"][index],"resultPath");
	}

	std::string GetSrcVideoPath(int index)
	{
		return GetStringS(root["body"][index],"srcVideoPath");
	}

	std::string GetSrcScriptPath(int index)
	{
		return GetStringS(root["body"][index],"srcScriptPath");
	}


public:

	PACKET_JOBLIST() : PACKET_BASE(_KEY_JOB_LIST)
	{
	};

	PACKET_JOBLIST(const Json::Value& root) : PACKET_BASE(_KEY_JOB_LIST , root)
	{
	}

	int GetSize()
	{
		return root["body"].size();
	}

	_JOB_INFO GetJobInfo(int index)
	{
		return _JOB_INFO(GetJobId(index) , GetS3Url(index) , GetResultPath(index) , GetSrcVideoPath(index) , GetSrcScriptPath(index) );
			
	}

	std::string Dump()
	{
		char buf[1024 * 2];
		memset(buf , 0x00 , 1024 * 2);

		sprintf(buf , "job list size : %d " , GetSize());

		return buf;
		
	}

	std::string Dump(int index)
	{
		char buf[1024 * 2];
		memset(buf , 0x00 , 1024 * 2);

 			sprintf(buf , "GET_JOB[%d]  : job_id[%s] , S3Url[%s] , resultPath[%s] , srcVideoPath[%s] , srcScriptPath[%s]",
					index , GetJobId(index).c_str() , GetS3Url(index).c_str() , GetResultPath(index).c_str() , GetSrcVideoPath(index).c_str() , GetSrcScriptPath(index).c_str() );
		return buf;
	}
	
};


#endif
